﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Internal;
using Autodesk.AutoCAD.Runtime;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Point2d = Autodesk.AutoCAD.Geometry.Point2d;
using Point3d = Autodesk.AutoCAD.Geometry.Point3d;

namespace WCAD
{
    public class OpenCV
    {
        [CommandMethod("YYY")]
        public void YYY()
        {
            Mat src = new Mat(@"C:\Users\Administrator\Desktop\1.png", ImreadModes.AnyColor | ImreadModes.AnyDepth);
            // 将图像转换为灰度图像
            Mat gray = new Mat();
            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
            // 应用阈值化函数
            double threshValue = 127;
            double maxValue = 255;
            Mat thresh = new Mat();
            Cv2.Threshold(gray, thresh, threshValue, maxValue, ThresholdTypes.Binary);
            var hierarchy = new Mat();
            Cv2.FindContours(thresh, out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            // 绘制轮廓
            Cv2.DrawContours(src, mats, -1, new Scalar(0, 0, 255), 2);
            // 显示结果
            Cv2.ImShow("original", src);
            Cv2.WaitKey(0);
        }
        [CommandMethod("YY")]
        public void YY()
        {
            Mat src = new Mat(@"C:\Users\Administrator\Desktop\1.png", ImreadModes.AnyColor | ImreadModes.AnyDepth);
            // 将图像转换为灰度图像
            Mat gray = new Mat();
            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
            // 应用阈值化函数
            double threshValue = 127;
            double maxValue = 255;
            Mat thresh = new Mat();
            Cv2.Threshold(gray, thresh, threshValue, maxValue, ThresholdTypes.Binary);
            var hierarchy = new Mat();
            Cv2.FindContours(thresh, out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            // 绘制轮廓
            Cv2.DrawContours(src, mats, -1, new Scalar(0, 0, 255), 2);
            // 显示结果
            Cv2.ImShow("original", src);
            Cv2.WaitKey(0);
        }
        [CommandMethod("ASA")]
        public void ASA()
        {
            if (!UmUserMethod.SelectEntities(out List<Entity> ents)) return;
            Extents3d extents = EmEntityMethod.GetExtents3d(ents);
            Point3d po = EmEntityMethod.CenterPoint(ents);
            Line3d line3D = new Line3d(po, po + new Vector3d(10, 0, 0));
            Matrix3d matrix = Matrix3d.Displacement(new Point3d(10, 10, 0) - extents.MinPoint) * Matrix3d.Mirroring(line3D);
            List<Curve> curves = new List<Curve>();
            foreach (var item in ents)
            {
                if (item is Curve)
                {
                    if (item is Polyline pl)
                    {
                        List<Curve> cus = PmPolylineMethod.ExplodePolyline(pl);
                        foreach (var cu in cus)
                        {
                            cu.TransformBy(matrix);
                            curves.Add(cu);
                        }
                    }
                    else
                    {
                        Curve curve = item.Clone() as Curve;
                        curve.TransformBy(matrix);
                        curves.Add(curve);
                    }

                }
            }
            double width = extents.MaxPoint.X - extents.MinPoint.X;
            double height = extents.MaxPoint.Y - extents.MinPoint.Y;
            Scalar black = new Scalar(0, 0, 0);
            int type = MatType.CV_8UC3;  // 指定数据类型
            Mat src = new Mat(new Size(width + 20, height + 20), type, black);
            LineTypes types = LineTypes.Link8;
            Scalar scalar = new Scalar(255, 255, 255);
            foreach (var item in curves)
            {
                if (item is Line line)
                {
                    Point pt1 = new Point(line.StartPoint.X, line.StartPoint.Y);
                    Point pt2 = new Point(line.EndPoint.X, line.EndPoint.Y);
                    Cv2.Line(src, pt1, pt2, scalar, 1, types, 0);
                }
                else if (item is Circle circle)
                {
                    Point center = new Point(circle.Center.X, circle.Center.Y);
                    Cv2.Circle(src, center, (int)circle.Radius, scalar, 1, types, 0);
                }
            }
            //Cv2.ImShow("src image", src);
            // Cv2.WaitKey();
            src.SaveImage("3.png");
            //Mat src = new Mat("3.png", ImreadModes.AnyColor | ImreadModes.AnyDepth);
            //Mat src = new Mat((int)width, (int)height, ImreadModes.AnyColor | ImreadModes.AnyDepth,);
            //Cv2.ImShow("original", src);
            //return;
            // 将图像转换为灰度图像
            Mat gray = new Mat();
            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
            gray.SaveImage("4.png");
            // 应用阈值化函数
            double threshValue = 127;
            double maxValue = 255;
            Mat thresh = new Mat();
            Cv2.Threshold(gray, thresh, threshValue, maxValue, ThresholdTypes.Binary);
            thresh.SaveImage("5.png");
            var hierarchy = new Mat();
            //Cv2.FindContours(thresh, out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            Cv2.FindContours(thresh, out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxTC89KCOS);
            Cv2.FindContours(thresh, out Point[][] poss, out HierarchyIndex[] hie, RetrievalModes.External, ContourApproximationModes.ApproxTC89KCOS);
            List<Point3d> pos = new List<Point3d>();
            foreach (var item in poss)
            {
                List<Point3d> ps = new List<Point3d>();
                foreach (Point point in item)
                {
                    ps.Add(po + new Vector3d((point.X - width / 2) - 10, -(point.Y - height / 2) + 10, 0));
                }
                Polyline polyline = PmPolylineMethod.CreatePolyline(ps, true);
                polyline.ColorIndex = 2;
                EmEntityMethod.AddEntity(polyline);
            }
            //List<DBPoint> points = new List<DBPoint>();
            //foreach (var item in pos)
            //{
            //    DBPoint dBPoint = new DBPoint(item);
            //    dBPoint.ColorIndex = 2;
            //    points.Add(dBPoint);
            //}
            //EmEntityMethod.AddEntities(points);
            
            for (int i = 0; i < 10000; i++)
            {
                Cv2.FindContours(thresh, out mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxTC89KCOS);
            }
            // 绘制轮廓
            Cv2.DrawContours(src, mats, -1, new Scalar(0, 0, 255), 2);
            src.SaveImage("6.png");
            // 显示结果
            //Cv2.ImShow("original", src);
            //Cv2.SetWindowProperty("original", WindowPropertyFlags.Fullscreen, 1);
            //Cv2.WaitKey(0);
            //return;
            //Cv2.ImShow("threshold", thresh);
            Mat mat = src;
            int w = mat.Width;
            int h = mat.Height;

            // 遍历所有像素，将红色通道值大于128的像素设为蓝色
            //double dd = 1.1 / d;
            for (int row = 0; row < h; row++)
            {
                for (int col = 0; col < w; col++)
                {
                    Vec3b color = mat.At<Vec3b>(row, col);
                    var sss = color[2];
                    if (color[0] == 0 && color[1] == 0 && color[2] == 255)
                    {
                        pos.Add(po + new Vector3d((col - w / 2), -(row - h / 2), 0));
                    }
                }
            }
            //Cv2.WaitKey(0);

        }
        [CommandMethod("CCCC")]
        public void CCCC()
        {
            //int rows = 500;   // 指定行数
            //int cols = 500;   // 指定列数
            //Scalar white = new Scalar(255, 255, 255);
            //int type = MatType.CV_8UC3;  // 指定数据类型
            //Mat src = new Mat(rows, cols, type,white);
            //Mat src1 = new Mat(rows, cols, type,white);

            //Point pt1 = new Point(50, 50);
            //Point pt2 = new Point(300, 50);
            //Point pt3 = new Point(50, 300);
            //Point pt4 = new Point(100, 100);
            //Scalar scalar = new Scalar(0, 0, 0);
            //Cv2.Line(src, pt1, pt2, scalar, 1, LineTypes.AntiAlias, 0);
            //Cv2.Line(src, pt1, pt3, scalar, 1, LineTypes.AntiAlias, 0);
            //Cv2.Line(src, pt2, pt3, scalar, 1, LineTypes.AntiAlias, 0);
            //Cv2.Line(src, pt1, pt4, scalar, 1, LineTypes.AntiAlias, 0);
            if (!UmUserMethod.SelectEntities(out List<Entity> ents)) return;
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            Transaction tr = db.TransactionManager.StartTransaction();
            ObjectId id = ObjectId.Null;
            using (tr)
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
                BlockTableRecord btr = new BlockTableRecord();
                btr.Name = DateTime.Now.ToString("yyyyMMddHHmmss");
                id = bt.Add(btr);
                tr.AddNewlyCreatedDBObject(btr, true);
                foreach (Entity ent in ents)
                {
                    Entity ent1 = ent.Clone() as Entity;
                    btr.AppendEntity(ent1);
                    tr.AddNewlyCreatedDBObject(ent1, true);
                }
                tr.Commit();
            }
            Extents3d extents = EmEntityMethod.GetExtents3d(ents);
            Point3d po = EmEntityMethod.CenterPoint(ents);
            double width = extents.MaxPoint.X - extents.MinPoint.X;
            //double d = width > 1000 ? 0.3 : 10;
            //width *= d;
            //if (width > 1920) width = 1920;
            double height = extents.MaxPoint.Y - extents.MinPoint.Y;
            //height *= d;
            //if (height > 1080) height = 1080;
            //if (width < 200)
            //{
            //    width *= 10;
            //    height *= 10;
            //}
            //System.Drawing.Bitmap bitmap = System.Drawing.Bitmap.FromHbitmap(Utils.GetBlockImage(id, 600, 600, Autodesk.AutoCAD.Colors.Color.FromRgb(0, 0, 0)));
            System.Drawing.Bitmap bitmap = System.Drawing.Bitmap.FromHbitmap(Utils.GetBlockImage(id, (int)width, (int)height, Autodesk.AutoCAD.Colors.Color.FromRgb(0, 0, 0)));
            bitmap.Save("1.png");
            using (var trans = WCAD.Trans)
            {
                id.GetObject(OpenMode.ForWrite).Erase();
                trans.Commit();
            }
            Mat src = new Mat("1.png", ImreadModes.AnyColor | ImreadModes.AnyDepth);
            //Mat src = new Mat((int)width, (int)height, ImreadModes.AnyColor | ImreadModes.AnyDepth,);
            //Cv2.ImShow("original", src);
            //return;
            // 将图像转换为灰度图像
            Mat gray = new Mat();
            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);

            // 应用阈值化函数
            double threshValue = 127;
            double maxValue = 255;
            Mat thresh = new Mat();
            Cv2.Threshold(gray, thresh, threshValue, maxValue, ThresholdTypes.Binary);
            var hierarchy = new Mat();
            //Cv2.FindContours(thresh, out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            //Cv2.FindContours(thresh, out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            Cv2.FindContours(thresh, out Point[][] ps, out HierarchyIndex[] hi, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            //RotatedRect rotated = Cv2.MinAreaRect(ps[0]);
            Cv2.MinEnclosingCircle(ps[0],out Point2f point1,out float r);
            //rotated.Size.
            // 绘制轮廓
            //Cv2.DrawContours(src, mats, -1, new Scalar(0, 0, 255), 2);
            // 显示结果
            //Cv2.ImShow("original", src);
            //Cv2.SetWindowProperty("original", WindowPropertyFlags.Fullscreen, 1);
            //Cv2.ImShow("threshold", thresh);
            Mat mat = src;
            int w = mat.Width;
            int h = mat.Height;
            double dd = 1.1;

            //Point3d point = po + new Vector3d((rotated.Center.X - w / 2) * dd, -(rotated.Center.Y - h / 2) * dd, 0);
            Point3d point = po + new Vector3d((point1.X - w / 2) * dd, -(point1.Y - h / 2) * dd, 0);
            //List<Line> lines = new List<Line>();
            //double width1 = rotated.Size.Width*dd;
            //double height1 = rotated.Size.Height*dd;
            //lines.Add(new Line(point + new Vector3d(-width1 / 2, height1 / 2, 0), point + new Vector3d(width1 / 2, height1 / 2, 0)));
            //lines.Add(new Line(point + new Vector3d(-width1 / 2, -height1 / 2, 0), point + new Vector3d(width1 / 2, -height1 / 2, 0)));
            //lines.Add(new Line(point + new Vector3d(-width1 / 2, -height1 / 2, 0), point + new Vector3d(-width1 / 2, height1 / 2, 0)));
            //lines.Add(new Line(point + new Vector3d(width1 / 2, -height1 / 2, 0), point + new Vector3d(width1 / 2, height1 / 2, 0)));
            //double angle = rotated.Angle/180*Math.PI;
            //Matrix3d matrix = Matrix3d.Rotation(angle, -Vector3d.ZAxis, point);
            //foreach (var item in lines)
            //{
            //    item.TransformBy(matrix);
            //}
            //EmEntityMethod.AddEntities(lines);
            Circle circle = new Circle()
            {
                Center = point,
                Radius = r * dd
            };
            EmEntityMethod.AddEntity(circle);
        }
        [CommandMethod("QQS")]
        public void QQ()
        {
            //int rows = 500;   // 指定行数
            //int cols = 500;   // 指定列数
            //Scalar white = new Scalar(255, 255, 255);
            //int type = MatType.CV_8UC3;  // 指定数据类型
            //Mat src = new Mat(rows, cols, type,white);
            //Mat src1 = new Mat(rows, cols, type,white);

            //Point pt1 = new Point(50, 50);
            //Point pt2 = new Point(300, 50);
            //Point pt3 = new Point(50, 300);
            //Point pt4 = new Point(100, 100);
            //Scalar scalar = new Scalar(0, 0, 0);
            //Cv2.Line(src, pt1, pt2, scalar, 1, LineTypes.AntiAlias, 0);
            //Cv2.Line(src, pt1, pt3, scalar, 1, LineTypes.AntiAlias, 0);
            //Cv2.Line(src, pt2, pt3, scalar, 1, LineTypes.AntiAlias, 0);
            //Cv2.Line(src, pt1, pt4, scalar, 1, LineTypes.AntiAlias, 0);
            if (!UmUserMethod.SelectEntities(out List<Entity> ents)) return;
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            Transaction tr = db.TransactionManager.StartTransaction();
            ObjectId id = ObjectId.Null;
            using (tr)
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
                BlockTableRecord btr = new BlockTableRecord();
                btr.Name = DateTime.Now.ToString("yyyyMMddHHmmss");
                id = bt.Add(btr);
                tr.AddNewlyCreatedDBObject(btr, true);
                foreach (Entity ent in ents)
                {
                    Entity ent1 = ent.Clone() as Entity;
                    btr.AppendEntity(ent1);
                    tr.AddNewlyCreatedDBObject(ent1, true);
                }
                tr.Commit();
            }
            Extents3d extents = EmEntityMethod.GetExtents3d(ents);
            Point3d po = EmEntityMethod.CenterPoint(ents);
            double width = extents.MaxPoint.X - extents.MinPoint.X;
            double d = 500/(extents.MaxPoint.DistanceTo(extents.MinPoint));
            width *= d;
            //if (width > 1920) width = 1920;
            double height = extents.MaxPoint.Y - extents.MinPoint.Y;
            height *= d;
            //if (height > 1080) height = 1080;
            //if (width < 200)
            //{
            //    width *= 10;
            //    height *= 10;
            //}
            //System.Drawing.Bitmap bitmap = System.Drawing.Bitmap.FromHbitmap(Utils.GetBlockImage(id, 600, 600, Autodesk.AutoCAD.Colors.Color.FromRgb(0, 0, 0)));
            System.Drawing.Bitmap bitmap = System.Drawing.Bitmap.FromHbitmap(Utils.GetBlockImage(id, (int)width, (int)height, Autodesk.AutoCAD.Colors.Color.FromRgb(0, 0, 0)));
            //var bb = Utils.GetBlockImage(id, (int)width, (int)height, Autodesk.AutoCAD.Colors.Color.FromRgb(0, 0, 0));
            bitmap.Save(@"D:\WCAD本地\WCAD\WCAD\bin\x64\Debug\1.png");
            using (var trans = WCAD.Trans)
            {
                id.GetObject(OpenMode.ForWrite).Erase();
                trans.Commit();
            }
            Mat src = new Mat(@"D:\WCAD本地\WCAD\WCAD\bin\x64\Debug\1.png", ImreadModes.AnyColor | ImreadModes.AnyDepth);
            //Mat src = new Mat(bb);
            //Mat src = new Mat((int)width, (int)height, ImreadModes.AnyColor | ImreadModes.AnyDepth,);
            //Cv2.ImShow("original", src);
            //return;
            // 将图像转换为灰度图像
            Mat gray = new Mat();
            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);

            // 应用阈值化函数
            double threshValue = 127;
            double maxValue = 255;
            Mat thresh = new Mat();
            Cv2.Threshold(gray, thresh, threshValue, maxValue, ThresholdTypes.Binary);
            var hierarchy = new Mat();
            //Cv2.FindContours(thresh, out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            Cv2.FindContours(thresh, out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

            // 绘制轮廓
            Cv2.DrawContours(src, mats, -1, new Scalar(0, 0, 255), 2);
            // 显示结果
            //Cv2.ImShow("original", src);
            //Cv2.SetWindowProperty("original", WindowPropertyFlags.Fullscreen, 1);
            //Cv2.ImShow("threshold", thresh);
            Mat mat = src;
            int w = mat.Width;
            int h = mat.Height;
            List<Point3d> pos = new List<Point3d>();
            // 遍历所有像素，将红色通道值大于128的像素设为蓝色
            double dd = 1.1 / d;
            for (int row = 0; row < h; row++)
            {
                for (int col = 0; col < w; col++)
                {
                    Vec3b color = mat.At<Vec3b>(row, col);
                    var sss = color[2];
                    if (color[0] == 0 && color[1] == 0 && color[2] == 255)
                    {
                        pos.Add(po + new Vector3d((col - w / 2) * dd, -(row - h / 2) * dd, 0));
                    }
                }
            }
            //Cv2.WaitKey(0);
            List<DBPoint> points = new List<DBPoint>();
            foreach (var item in pos)
            {
                DBPoint dBPoint = new DBPoint(item);
                dBPoint.ColorIndex = 2;
                points.Add(dBPoint);
            }
            EmEntityMethod.AddEntities(points);
            //src.SaveImage("2.png");
            //Cv2.ImShow("src image", src);
            //Cv2.WaitKey();
            //Cv2.FindContours
            //Mat gray = new Mat();
            //Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);

            //// 只查找最外层轮廓
            ////var contours = new List<Point[]>();

            //var hierarchy = new Mat();
            //Cv2.FindContours(gray,out Mat[] mats, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

            //// 在原始图像上绘制轮廓
            //Cv2.DrawContours(src, mats, -1, Scalar.Red, thickness: 5);

            //Cv2.ImShow("Result", src);
            //Cv2.WaitKey(0);
            //Cv2.DestroyAllWindows();
        }
        [CommandMethod("QQQQQ")]
        public void QQQQQ()
        {
            if (!UmUserMethod.GetEntity(out Line line1)) return;
            if (!UmUserMethod.GetEntity(out Line line2)) return;
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            for (int i = 0; i < 100000; i++)
            {
                List<Point3d> pos = new List<Point3d>();
                Point3dCollection ps = new Point3dCollection();
                line1.IntersectWith(line2, Intersect.OnBothOperands, ps, IntPtr.Zero, IntPtr.Zero);
                foreach (Point3d item in ps)
                {
                    pos.Add(item);
                }

            }
            stopwatch.Stop();
            WCAD.Ed.WriteMessage("cad自己求相交100000次" + stopwatch.ElapsedMilliseconds.ToString() + "毫秒");
            stopwatch.Restart();
            for (int i = 0; i < 100000; i++)
            {

                OpenCvSharp.Line3D line3d1 = new Line3D(line1.Delta.X, line1.Delta.Y, line1.Delta.Z, line1.StartPoint.X, line1.StartPoint.Y, line1.StartPoint.Z);
                OpenCvSharp.Line3D line3d2 = new Line3D(line2.Delta.X, line2.Delta.Y, line2.Delta.Z, line2.StartPoint.X, line2.StartPoint.Y, line2.StartPoint.Z);
            }
            stopwatch.Stop();
            WCAD.Ed.WriteMessage("opencv求相交100000次" + stopwatch.ElapsedMilliseconds.ToString() + "毫秒");
        }
    }
}
